# coding=UTF-8
import time
from typing import List

from common.enums import Enums
from database.mapper import stock_day_k, stock_month_k
from database.mapper.stock_day_k import StockDayK
from service import data_service
from utils import date_util, json_util, http_util


def rt_day_k_n(code, size, rt_price) -> List[StockDayK]:
    res = stock_day_k.select_n(code, size)
    if not res or len(res) == 0:
        init_day_k(code)
        res = stock_day_k.select_n(code, size)
    else:
        diff_days = date_util.diff_days(res[0].rq, date_util.str_to_date(date_util.find_last_valid_day(), '%Y-%m-%d'))
        if diff_days > 0:  # 如果最新的数据不是最新一天的数据则更新
            get_day_k_size(code, diff_days)
            res = stock_day_k.select_n(code, size)
    res[0].sp = rt_price
    return res


# 实时的k线
# 时间逆序从大到小
def day_k_size_rt(code, size, rt_price):
    res = day_k_size(code, size)
    res[0]['sp'] = rt_price
    if rt_price > res[0]['max']:
        res[0]['max'] = rt_price
        stock_day_k.update(res[0])
    if rt_price < res[0]['min']:
        res[0]['min'] = rt_price
        stock_day_k.update(res[0])
    return res


# 实时的k线
# 时间逆序从大到小
def day_k_size(code, size):
    res = stock_day_k.select_size(code, size)
    if not res or len(res) == 0:
        init_day_k(code)
        res = stock_day_k.select_size(code, size)
    else:
        rq = res[0]['rq']
        v_rq = date_util.find_last_valid_day()
        diff_days = date_util.diff_days(rq, date_util.str_to_date(v_rq, '%Y-%m-%d'))
        if diff_days > 0:  # 如果最新的数据不是最新一天的数据则更新
            get_day_k_size(code, diff_days)
            res = stock_day_k.select_size(code, size)
    return res


# list : 要求时间顺序 从大到小
def record_day_k(data_list):
    if not data_list or len(data_list) == 0:
        return
    code = data_list[0]['code']
    res = stock_day_k.select(code)
    if res:  # 部分更新
        rq = res['rq']
        d_rq = data_list[len(data_list) - 1]['rq']
        # 如果日期差异过大重新初始化
        if date_util.diff_days(date_util.str_to_date(d_rq, '%Y-%m-%d'), rq) >= 0:
            stock_day_k.delete_interval(code, rq)
            stock_day_k.insert_multiple(data_list)
            return
    init_day_k(code)


# 记录所有数据
def record_day_k_all(data_list):
    if not data_list or len(data_list) == 0:
        return
    code = data_list[0]['code']
    stock_day_k.delete_interval(code, '1990-01-01')
    stock_day_k.insert_multiple(data_list)


# 初始化
def init_day_k(code):
    print('初始化日K,start,code' + code)
    k_lines = get_day_k_size(code, 12000)
    print('查询长度' + str(len(k_lines)))
    record_day_k_all(k_lines)
    print('初始化日K,end,code' + code)


# http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&
# fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,
# f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,
# f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,
# f190,f191,f192,f107,f111,f86,f177,f78,f110,f262,f263,f264,f267,f268,f250,f251,f252,f253,
# f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f193,f196,f194,
# f195,f197,f80,f280,f281,f282,f284,f285,f286,f287,f292&secid=1.600031&cb=jQuery1124026036177405242544_1625469920756&_=1625469920809
# 市值

# http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&
# fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,
# f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,
# f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f262,f263,
# f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f193,
# f196,f194,f195,f197,f80,f280,f281,f282,f284,f285,f286,f287,f292&secid=1.600031&cb=jQuery112409142735672543986_1627287642804&_=1627287642805

# 返回参数日期从大到小
def get_day_k_size(code, size):
    time_stamp = int(round(time.time() * 1000))
    if size == 12000 and code == '000000':
        beg = '19900101'
        path_url = 'http://push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery112404579791166364856_' + str(
            time_stamp) + '&secid=1.000001&ut=fa5fd1943c7b386f172d6893dbfba10b' \
                          '&fields1=f1,f2,f3,f4,f5&fields2=f51,f52,f53,f54,f55,f56,f57,f58&klt=101' \
                          '&fqt=0&beg=' + beg + '&end=20500101&_=' + str(time_stamp)
    else:
        path_url = 'http://66.push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery1124015253095575263576_' + str(
            time_stamp) + '&secid=' + str(data_service.stock(code)['exchange']) + '.' + str(code) + \
                   '&ut=fa5fd1943c7b386f172d6893dbfba10b&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5' \
                   '&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58&klt=101' \
                   '&fqt=0&end=20500101&lmt=' + str(size) + '&_=' + str(time_stamp)
    # resp = requests.get(path_url)
    resp_content = str(http_util.request_get(path_url).content.decode('utf-8'))
    if resp_content == '':
        print("\033[32m$$$$$$$$$$$$$$$$$获取日K线地址" + path_url + "不能使用$$$$$$$$$$$$$$$\033[0m")
    days_info_str = resp_content.split('(')[1].split(')')[0]
    days_info_str = days_info_str.replace('null', '""')
    resp_json = json_util.to_json(days_info_str)
    if resp_json['data'] == '':
        print("code:" + code + ":请求k线为空")
        return []
    klines = resp_json['data']['klines']
    return format_k_lines(code, klines)


def format_k_lines(code, klines):
    k_lines = []
    klines_l = len(klines)
    for i in range(klines_l):
        k_lines.append(format_k_line(code, klines[klines_l - i - 1]))
    return k_lines


def format_k_line(code, kline):
    kline_arr = kline.split(',')
    day_k_info = {}
    day_k_info[Enums.Stock.code.value] = code
    day_k_info[Enums.Stock.rq.value] = kline_arr[0]
    day_k_info[Enums.Stock.kp.value] = kline_arr[1]
    day_k_info[Enums.Stock.sp.value] = kline_arr[2]
    day_k_info[Enums.Stock.max.value] = kline_arr[3]
    day_k_info[Enums.Stock.min.value] = kline_arr[4]
    day_k_info[Enums.Stock.cjl.value] = kline_arr[5]
    day_k_info[Enums.Stock.cje.value] = kline_arr[6]
    day_k_info[Enums.Stock.zf.value] = kline_arr[7]
    return day_k_info


# 5 或者 30
def cal_the_k(code, flag):
    if flag != 5 and flag != 30:
        return []
    day_all_ks = stock_day_k.select_all_asc(code)
    day_all_ks.reverse()
    k_len = len(day_all_ks)
    if k_len <= 0:
        return []
    start_flag = 1
    k_info = {"code": code, "rq": "", "kp": 0, "sp": 0, "max": 0, "min": 999999}
    begin_rq = day_all_ks[k_len - 1]['rq']
    result_ks = []
    for i in range(k_len):
        dayk = day_all_ks[i]
        rq = date_util.date_to_str(dayk['rq'], '%Y-%m-%d')
        if start_flag:  # 新开始的一个周期
            k_info['sp'] = float(dayk['sp'])
            k_info['rq'] = date_util.date_to_str(dayk['rq'], '%Y-%m-%d')
            start_flag = 0
        trigger_flag = 0
        if flag == 5:
            flag_num = date_util.isoweekdaystr(rq)
            last_day_rq = date_util.date_to_str(k_info['rq'], '%Y-%m-%d')
            last_week_num = date_util.isoweekdaystr(k_info['rq'])
            diff_days = date_util.diff_days_str(rq, last_day_rq)
            if (diff_days > last_week_num and flag == 5):  # 超过了当前星期
                trigger_flag = 1
        elif flag == 30:
            flag_num = int(rq[-2:])
            last_day_rq = k_info['rq']
            last_month = last_day_rq[5:7]
            this_month = rq[5:7]
            if last_month != this_month:
                trigger_flag = 1
        else:
            return []
        if trigger_flag == 1:
            print(code + '超过了一个周期' + last_day_rq)
            # 进行上一周的封顶 和 本周的开始
            last_day_k = json_util.info_to_json(day_all_ks[i - 1])
            k_info['kp'] = float(last_day_k['kp'])
            result_ks.append(k_info)  # 添加在队列
            k_info = {"code": code, "rq": "", "kp": 0, "sp": 0, "max": 0, "min": 999999}
            k_info['sp'] = float(dayk['sp'])
            k_info['rq'] = date_util.date_to_str(dayk['rq'], '%Y-%m-%d')
            k_info['max'] = float(dayk['max'])
            k_info['min'] = float(dayk['min'])
            continue
        max = float(dayk['max'])
        min = float(dayk['min'])
        if k_info['max'] < max:
            k_info['max'] = max
        if k_info['min'] > min:
            k_info['min'] = min
        if flag_num == 1 or rq == begin_rq:
            k_info['kp'] = float(dayk['kp'])
            result_ks.append(k_info)
            k_info = {"code": code, "rq": "", "kp": 0, "sp": 0, "max": 0, "min": 999999}
            start_flag = 1  # 一个周期的结束
    return result_ks


# 初始化
def init_month_k(code):
    result_ks = cal_the_k(code, 30)
    stock_month_k.delete_interval(code, '1990-01-01')
    stock_month_k.insert_multiple(result_ks)


if __name__ == '__main__':
    # dks = day_k_size_rt('000002', 10, 100)
    dks = get_day_k_size('601633', 10)
    # dks = day_ks_gp('601633', '2021-03-09', 10)
    # init_month_k('600089')
    print("end")
